package com.woniu.his.bms.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Snowflake;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.woniu.his.app.client.AppRegistrationClient;
import com.woniu.his.app.client.result.RegHistoryResult;
import com.woniu.his.bms.common.BmsResultCode;
import com.woniu.his.bms.common.enums.BmsStatusEnums;
import com.woniu.his.bms.infra.model.BillsRecord;
import com.woniu.his.bms.infra.mapper.BillsRecordMapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.woniu.his.bms.infra.model.InvoiceRecord;
import com.woniu.his.bms.service.BillsRecordService;
import com.woniu.his.bms.service.InvoiceRecordService;
import com.woniu.his.bms.service.dto.BillRecordDto;
import com.woniu.his.cms.client.NonDrugItemRecordClient;
import com.woniu.his.cms.client.result.NonDrugItemResult;
import com.woniu.his.exception.HisException;
import com.woniu.his.mms.client.HerbalPrescriptionClient;
import com.woniu.his.mms.client.MedicineClient;
import com.woniu.his.mms.client.result.HerbalPrescriptionResult;
import com.woniu.his.mms.client.result.MedicinePrescriptionReuslt;
import com.woniu.his.result.Result;
import com.woniu.his.bms.service.dto.BmsDoctorPatientFeeDto;
import com.woniu.his.cms.client.NonDrugClient;
import com.woniu.his.cms.client.result.DmsNonDrugResult;
import com.woniu.his.cms.client.result.NonDrugItemRecordQuerResult;
import com.woniu.his.mms.client.DrugManageClient;
import com.woniu.his.mms.client.result.*;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.embedded.netty.NettyWebServer;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * <p>
 * 账单记录 服务实现类
 * </p>
 *
 * @author chenbo
 * @since 2022-11-29
 */
@Service
public class BillsRecordServiceImpl extends ServiceImpl<BillsRecordMapper, BillsRecord> implements BillsRecordService {

    @Resource
    private Snowflake snowflake;

    @Resource
    private HerbalPrescriptionClient herbalPrescriptionClient;

    @Resource
    private MedicineClient medicineClient;

    @Resource
    private NonDrugItemRecordClient nonDrugItemRecordClient;

    @Resource
    private AppRegistrationClient appRegistrationClient;




    private static String app_id = "2021000121673919";

    // 商户私钥，您的PKCS8格式RSA2私钥
    private static String merchant_private_key = "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCIQPF0eV4GRY01doYPZq4Ak5iPbZXD94vzkSXEivq93CuxDRLpSIC18+kiGGcJKm/zG6e78zlINsFxqR+KOt76FFwAxvlzd6U4vNFZdu3jSTuKnINng/Lur7VIr0vzPgl7mdDwozfmDK8g4bLRZMS0IIx3QwRwbXphL8ez6xob50bQvIkoGSA0wq8gsTlJxAjS50EuWJGCXg2afph3QU86oVhRmPFvvmEs61Vku8vV5XI6dMvEGsZ7NdSirkJfr2C1bqFaRCkRGUKPIgR03kW1+FoSFXf1l/iU5qpT0Lg/t3eP9DLClCx0IBnqnr/hiLi+gt1duZ4BvZ0P7vXV5ut1AgMBAAECggEASEcTDrM3EmKgxqSJ9u+EDCA/hI4gLSVK4ziy7TDAVCjQMIp75q4kQOETYZfKSI1vd2nLL6OVVl5dfXq2lXAnSke0imECgKMOTSu0bh3tkW0Onbfq6OWQ39brdpQu2OimxR9SO+SJSYqe9/ViEzu+MMM3YCh32V/p1FYxPJrRbc0VkZ8idc7UVSFjhEVfOe3KO4L5DLCwJpzv0FR2aDjWWdbF5VPgRgiI66yq9dMAAp2fTW2/HSWk67J2ThjELlE7fy32TXAjPZSW+eYP2Ton4XrHUOM/bYbpCBXzxnA+UxhDo/dSayxZ/owuYvJJN0uf5rgtob3SHZQSXpUNQnSlnQKBgQDp2hPRnfZYDe6pCQ4lLpZelkef6g/P+o3uSnX+QDBx9f6DjQ3SKAdAffRuFZQIkKTWOafEq9NEjkR5YtMGfeZ1eJAEh0AS0apQNuEgiFFUAmYA7LKYaEXMnQ5VuL9Q/fJD8A1OdQx/jbbxNyEOYdpnoj3tyBIovtRSDEPQhosbEwKBgQCVKIVim1Xc7M+7vGTWLq9NXuDLeIJ7PdQ2obAdSrIeTpOAda36Ry/CtqAyxsO/9azfG8B0LpBRzvZVlSZg80rxDVVVnTS6CK2ObDddEAWIIV/uJ03TTOpTCGJT6SF3I1MHbQLv+mNIWV1ZGhthB/DF5Yi7K4/DO6JybXPnevtoVwKBgCbu3sPUV7IbR7OuxUMdeX1v6abPEijfHwggL3rP9wDSIriGIFnvvh1Xmv1E7GtsoXTlDnBo5viP8wh+koGPLnI6S0fluJ4peAB40oxXBatF5vOadLV5Dr3dHAjbhEaYsN/stFpulFEcJ+wK8J7zXahJU6Ql3hgYhULPte6ep8QvAoGACuNaWUhdjDL9NwcZlUjzIwK6BiBV5gktZI+I+5poRi4WNlpgyNRJeD08lHhN8cVNSTwNYG3FuzMQaE7q7kjUP6RphkZjgvD/OlZL9E8nGDjXd9sGo1YKBOWnx9hMyRWbCf+7Jylv9egQGGD/fqXFvaxzvrX/WJER2qiCvXMMxyECgYEAuSGILB89kRst2++2PhI+adBg6Eplmd+gpDaeOZvAHdYflr952ITpRYW/Dym0ZJ9E7jX0EHp38gc62QwxZ9KnnhgSdgPp5due1THE8Tj//ht+i9eNgQ9N2kUgiUcRWuLa+15Ux5DHaI8Y+ieDRkqUeQV8I46W+J3OS0z47tdYwiU=";

    // 支付宝公钥,查看地址：https://openhome.alipay.com/platform/keyManage.htm 对应APPID下的支付宝公钥。
    private static String alipay_public_key = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlW3LSu+XZJ0Z5QdytgDc2lN5A/RIg7hR1b9BLpJLBbptXRhP0FTs5p5k49fur/AGo8XaYpgMh1tOOFrr31mx7+yHuovZdtYsvH2dzP/arf0vYjR5JHA79c0fKNwut6TzfkCMrfUhkhCwLIa5a9pyHxoieHj4wR3U+0cWtf4T3hWo/0TfbeahXniiV/0RobjBBmrqnQ55YbXsgx/cf4JP5oaaWUIGY3vBKWkZswoyuCzULbvYhLVGb/eXipDW7y1tqRkLo8ulm5AvKtaZn1VwSt9rkdmUYuT/2IIEd3Jbg8103KoKNHUmGcy0X2Oe/KeAllsdrDVk8HuGKFME7hD8+wIDAQAB";

    // 服务器异步通知页面路径  需http://格式的完整路径，不能加?id=123这类自定义参数，必须外网可以正常访问
    private static String notify_url = "http://";

    // 页面跳转同步通知页面路径 需http://格式的完整路径，不能加?id=123这类自定义参数，必须外网可以正常访问
    private static String return_url = "http://localhost:8080/order-record.html";

    // 签名方式
    private static String sign_type = "RSA2";

    // 字符编码格式
    private static String charset = "utf-8";

    // 支付宝网关
    private static String gatewayUrl = "https://openapi.alipaydev.com/gateway.do";

    @Resource
    private HerbalPrescriptionClient herbalPresent;


    @Resource
    private DrugManageClient drugManageClient;

    @Resource
    private NonDrugClient nonDrugClient;

    @Resource
    private InvoiceRecordService invoiceRecordService;

    @Resource
    private RocketMQTemplate rocketMQTemplate;


    @Override
    public BillRecordDto createBillRecord(String billType,BigDecimal amount) {

        BillsRecord billsRecord = new BillsRecord();
        billsRecord.setBillNo("bill" + snowflake.nextId());
        billsRecord.setCreateTime(DateUtil.formatDateTime(new Date()));
        billsRecord.setStatus(BmsStatusEnums.NOT_PAY.getCode());
        billsRecord.setType(billType);
        save(billsRecord);
        InvoiceRecord invoiceRecord = new InvoiceRecord();
        invoiceRecord.setAmount(amount);
        invoiceRecord.setBillId(billsRecord.getId());
        invoiceRecord.setCreateTime(new Date());
        invoiceRecord.setFreezeStatus(BmsStatusEnums.NORMAL.getCode());
        invoiceRecord.setInvoiceNo(snowflake.nextId());
        invoiceRecord.setInvoiceId((long)2);
        invoiceRecord.setSettlementCatId((long) 1);
        invoiceRecordService.save(invoiceRecord);
        return BeanUtil.copyProperties(billsRecord,BillRecordDto.class);
    }

    @Override
    public BillRecordDto createBillRecord(String billType,BigDecimal amount ,Long caseHistoryId) {
        BillRecordDto billRecordDto = createBillRecord(billType, amount);
        billRecordDto.setCaseHistoryId(caseHistoryId);
        updateById(BeanUtil.copyProperties(billRecordDto,BillsRecord.class));
        return billRecordDto;
    }
    @Override
    public List<BillRecordDto> queryBillRecord(Long caseHistoryId) {
        List<BillsRecord> billsRecords = list(new QueryWrapper<BillsRecord>()
                .eq("case_history_id", caseHistoryId)
                .eq("status", BmsStatusEnums.NOT_PAY.getCode()));
        List<BillRecordDto> billRecordDtos = BeanUtil.copyToList(billsRecords, BillRecordDto.class);
        return billRecordDtos;
    }

    /**
     * 查询费用
     * @param caseHistoryId
     * @return
     */
    @Override
    public List<BmsDoctorPatientFeeDto> listFeeByCaseHistoryId(Long caseHistoryId) {

        List<BmsDoctorPatientFeeDto> dto = new ArrayList<>();
        Result<List<MedicineResult>> listResult = medicineClient.listByReg(caseHistoryId);
        Result<HerbalPrescriptionResult> herbalPrescriptionResultResult = herbalPresent.queryHerbalPrescriptionByCaseId(caseHistoryId);
//        if(listResult.getData().isEmpty()||herbalPrescriptionResultResult.getData().getHerbalItemDtos().isEmpty()) return null;
        List<MedicineResult> meList = listResult.getData();
        //先遍历成药处方
        for (MedicineResult medicineResult : meList) {
            List<DmsMedicineItemRecordResult> dmsMedicineItemRecordList = medicineResult.getDmsMedicineItemRecordList();
            if(dmsMedicineItemRecordList.size()<=0) continue;
            for (DmsMedicineItemRecordResult dmsMedicineItemRecordResult : dmsMedicineItemRecordList) {
                BmsDoctorPatientFeeDto bms = new BmsDoctorPatientFeeDto();
                Result<DrugResult> drugResultResult = drugManageClient.queryDrug(dmsMedicineItemRecordResult.getDrugId());
                bms.setFormat(drugResultResult.getData().getFormat());
                bms.setCurrentNum(dmsMedicineItemRecordResult.getNum()-dmsMedicineItemRecordResult.getUsageNum());
                bms.setItemName(medicineResult.getMedicinePrescriptionName());
                bms.setPrice(drugResultResult.getData().getPrice());
                bms.setType(medicineResult.getType());
                bms.setStatus(dmsMedicineItemRecordResult.getStatusMedicine());
                dto.add(bms);
            }
        }
        HerbalPrescriptionResult data = herbalPrescriptionResultResult.getData();
        List<HerbalItemResult> herbalItemDtos = data.getHerbalItemDtos();
        for (HerbalItemResult herbalItemDto : herbalItemDtos) {
            Result<DrugResult> drugResultResult = drugManageClient.queryDrug(herbalItemDto.getDrugId());
            BmsDoctorPatientFeeDto bms = new BmsDoctorPatientFeeDto();
            bms.setItemName(drugResultResult.getData().getGenericName());
            bms.setPrice(drugResultResult.getData().getPrice());
            bms.setFormat(drugResultResult.getData().getFormat());
            bms.setType(data.getType());
            bms.setType(data.getType());
            bms.setCurrentNum(herbalItemDto.getTotalNum()-herbalItemDto.getUsageNum());
            dto.add(bms);
        }

        Result<List<NonDrugItemRecordQuerResult>> listResult1 = nonDrugClient.queryResultByCaseId(caseHistoryId);
        List<NonDrugItemRecordQuerResult> data1 = listResult1.getData();
        if(data1.size() >=0 ){
            for (NonDrugItemRecordQuerResult nonDrugItemRecordQuerResult : data1) {
                Result<DmsNonDrugResult> result = nonDrugClient.queryById(nonDrugItemRecordQuerResult.getNoDrugId());
                if (result.getData()==null) continue;
                BmsDoctorPatientFeeDto bms = new BmsDoctorPatientFeeDto();
                bms.setStatus(nonDrugItemRecordQuerResult.getNonDrugItemStatus());
                bms.setType(nonDrugItemRecordQuerResult.getType());
                bms.setCurrentNum(null);
                bms.setFormat(result.getData().getNonDrugFormat());
                bms.setPrice(result.getData().getPrice());
                bms.setItemName(result.getData().getNonDrugName());
                dto.add(bms);
            }
        }

        return dto;
    }

    @Override
    public String pay(Long billId) throws AlipayApiException, UnsupportedEncodingException {

        BillsRecord billsRecord = getById(billId);
        String onPay=null;
        if(billsRecord==null) throw new HisException(BmsResultCode.BILL_NOT_EXISTS);

        System.out.println(billsRecord.toString());

        if (billsRecord.getType().equals(BmsStatusEnums.Bill_Record_type_REGISTRATION.getCode())) {
            Result<RegHistoryResult> regHistoryResultResult = appRegistrationClient.queryRegByBillId(billId);
            RegHistoryResult result = regHistoryResultResult.getData();
            if(!result.getStatus().equals(BmsStatusEnums.NOT_PAY.getCode())){
                throw new HisException(BmsResultCode.BILL_STATUS_EXCEPTION);
            }
            BigDecimal amount = invoiceRecordService.getOne(new QueryWrapper<InvoiceRecord>().eq("bill_id", billId)).getAmount();
            onPay = onPay(billsRecord.getBillNo(), String.valueOf(amount),"挂号","挂号");
        }
        if(billsRecord.getType().equals(BmsStatusEnums.Bill_Record_type_HERBAL.getCode())){
            Result<HerbalPrescriptionResult> result = herbalPrescriptionClient.queryHerbalPrescriptionByBillId(billId);
            HerbalPrescriptionResult data = result.getData();
            if(!data.getHerbalPrescriptionStatus().equals(BmsStatusEnums.NOT_PAY.getCode())){
                throw new HisException(BmsResultCode.BILL_STATUS_EXCEPTION);
            }
            onPay = onPay(billsRecord.getBillNo(), String.valueOf(data.getAmount()),"草药处方",data.getHerbalPrescriptionName());
        }
        if(billsRecord.getType().equals(BmsStatusEnums.Bill_Record_type_MEDICINE.getCode())){
            Result<MedicinePrescriptionReuslt> result = medicineClient.queryMedicinePrescriptionByBillId(billId);
            MedicinePrescriptionReuslt data = result.getData();
            if(data.getRefundStatus().equals(BmsStatusEnums.NOT_PAY.getCode())){
                throw new HisException(BmsResultCode.BILL_STATUS_EXCEPTION);
            }
            onPay = onPay(billsRecord.getBillNo(), String.valueOf(data.getAmount()), "成药处方", data.getMedicinePrescriptionName());
        }
        if(billsRecord.getType().equals(BmsStatusEnums.Bill_Record_type_TEST.getCode())
        ||billsRecord.getType().equals(BmsStatusEnums.Bill_Record_type_CHECK.getCode())
        ||billsRecord.getType().equals(BmsStatusEnums.Bill_Record_type_DISPOSITION.getCode())){
            Result<NonDrugItemResult> result = nonDrugItemRecordClient.queryNonDrugItemByBillId(billId);

            NonDrugItemResult data = result.getData();
            if(!data.getNonDrugItemStatus().equals(BmsStatusEnums.NOT_PAY.getCode())){
                throw new HisException(BmsResultCode.BILL_STATUS_EXCEPTION);
            }
            onPay = onPay(billsRecord.getBillNo(), String.valueOf(data.getAmount()), "非药品项目", data.getNonDrugName());
        }
        Message<String> message = MessageBuilder.withPayload(billsRecord.getBillNo()).build();
        System.out.println("====开始发延迟信息=========");
        rocketMQTemplate.syncSend("bill-pay-success",message,20000,2);

        return onPay;
    }

    @Override
    public void paySuccess(String billNo) {
        System.out.println("====执行延迟信息=========");

        BillsRecord billsRecord = getOne(new QueryWrapper<BillsRecord>().eq("bill_no", billNo));
        if(billsRecord.getType().equals(BmsStatusEnums.Bill_Record_type_REGISTRATION.getCode())){
            appRegistrationClient.paySuccess(billsRecord.getId());
        }
        if(billsRecord.getType().equals(BmsStatusEnums.Bill_Record_type_HERBAL.getCode())){
            herbalPrescriptionClient.paySuccess(billsRecord.getId());
        }
        if(billsRecord.getType().equals(BmsStatusEnums.Bill_Record_type_MEDICINE.getCode())){
            medicineClient.paySuccess(billsRecord.getId());
        }
        if(billsRecord.getType().equals(BmsStatusEnums.Bill_Record_type_TEST.getCode())
                ||billsRecord.getType().equals(BmsStatusEnums.Bill_Record_type_CHECK.getCode())
                ||billsRecord.getType().equals(BmsStatusEnums.Bill_Record_type_DISPOSITION.getCode())){
            nonDrugItemRecordClient.paySuccess(billsRecord.getId());
        }
        billsRecord.setStatus("NOT_REGIST");
        updateById(billsRecord);


    }

    private String onPay(String billNo, String amount, String billName, String content) throws AlipayApiException, UnsupportedEncodingException {
        AlipayClient alipayClient =  new DefaultAlipayClient( gatewayUrl,
                app_id,
                merchant_private_key,
                "json",
                charset,
                alipay_public_key,
                sign_type);  //获得初始化的AlipayClient
        AlipayTradePagePayRequest alipayRequest =  new AlipayTradePagePayRequest(); //创建API对应的request
        alipayRequest.setReturnUrl(return_url  );
        alipayRequest.setNotifyUrl(notify_url  ); //在公共参数中设置回跳和通知地址
        //商户订单号，商户网站订单系统中唯一订单号，必填
        String out_trade_no = new String(billNo.getBytes("ISO-8859-1"),"UTF-8");
        //付款金额，必填
        String total_amount = new String(amount.getBytes("ISO-8859-1"),"UTF-8");
        //订单名称，必填
        String subject = billName;
        //商品描述，可空
        String body = content;

        JSONObject bizContent = new JSONObject();
        bizContent.put("out_trade_no", out_trade_no);
        bizContent.put("total_amount", total_amount);
        bizContent.put("subject", subject);
        bizContent.put("product_code", "FAST_INSTANT_TRADE_PAY");
//            bizContent.put("time_expire", "2022-11-01 22:00:00");
        alipayRequest.setBizContent(bizContent.toString());
        String result = alipayClient.pageExecute(alipayRequest).getBody();
        return result;
    }
}
